﻿using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Common;
using DataExporter;
using DevExpress.Utils;
using DevExpress.XtraBars.Ribbon;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using FileHelpers;
using Timer = System.Windows.Forms.Timer;

namespace AutoSubmitter
{
    public partial class FormSubmitter : XtraForm
    {

        private string[] _files;
        private int _index;
        private string _fileDirectory;
        private Timer _submitTimer;
        private bool _readyToSubmit;
        private const string SubmitUrl = @"http://10.64.16.22/trffweb/saveSur.vio?method=doFxccxEdit&cdbh=0103&xtlb=04";
        private const string LoginUrl = @"http://10.64.16.22/trffweb";

        public FormSubmitter()
        {
            InitializeComponent();

            DataExporter.Helper.InitGrid(this.gridControl1, this.gridView1);
            gridView1.MouseMove += GridView1OnMouseMove;
            if (!HookerApi.Hook())
            {
                MessageBox.Show("初始化失败，请将本程序加入杀毒软件的信任列表后重新启动");
            }

            InitTimer();

            _writer = new StreamWriter("log.txt", true);
            _writer.WriteLine(DateTime.Now.ToString(CultureInfo.InvariantCulture));

            webBrowser1.ScriptErrorsSuppressed = true;
            webBrowser1.DocumentCompleted += OnWebBrowser1OnDocumentCompleted;
            webBrowser1.NewWindow += (sender, args) => { args.Cancel = true; };

        }

        private void GridView1OnMouseMove(object sender, MouseEventArgs mouseEventArgs)
        {
            //var hi = this.gridView1.CalcHitInfo(mouseEventArgs.Location);

            //if (hi.HitTest == GridHitTest.RowCell )//&& hi.Column.FieldName == "SubmitStatus"
            //{
            //    System.Diagnostics.Debug.WriteLine(hi.HitTest + hi.Column.FieldName);
            //    var r = this.gridView1.GetRow(hi.RowHandle) as Record;
            //    if (r != null)
            //    {
            //        hi.Column.ToolTip = r.TxWz;
            //    }

            //}
        }

        private void OnWebBrowser1OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs args)
        {
            this.textBoxUrl.Text = args.Url.ToString();
            LogMessage("navigated to: " + args.Url.ToString());
            var urlString = args.Url.ToString();
            if (LoginFinished(urlString)) //登陆完毕，自动跳到提交页面
            {
                LogMessage("登陆完毕，自动进入提交页面");
                this.webBrowser1.Navigate(SubmitUrl);
            }
            else if (urlString.Contains("commpage")) //提交页面载入完毕，可以提交了
            {
                _readyToSubmit = true;
            }
        }

        private static bool LoginFinished(string urlString)
        {
            return urlString.ToLower().Contains("login.frm?method=check");
        }

        private void InitTimer()
        {
            _submitTimer = new Timer();
            _submitTimer.Interval = 500;
            _submitTimer.Tick += new EventHandler(_submitTimer_Tick);
            _submitTimer.Stop();
        }

        void _submitTimer_Tick(object sender, EventArgs e)
        {
            _submitTimer.Stop();
            if (_records != null && _idx < _records.Length)
            {
                progressBar1.EditValue = _idx;
                var r = _records[_idx];
                var submitResult = SubmitResult.TimeOut;
                if (r.SubmitStatus != 1)
                {
                    labelCurrentLprNumber.Text = _records[_idx].LprNumber;

                    //if (_idx > 0)
                    //{
                    //    dataGridView1.Rows[_idx - 1].Selected = false;
                    //}
                    //dataGridView1.Rows[_idx].Selected = true;
                    //dataGridView1.FirstDisplayedScrollingRowIndex = _idx;

                    submitResult = FillForm(r, _idx);
                }

                if (_idx == _records.Length - 1)
                {
                    panelProgress.Visible = false;
                    MessageBox.Show("全部数据提交完毕", "完成提交", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    StopSubmit();
                }
                else if (!_stopSubmit)
                {
                    _submitTimer.Start();
                }
                //if (submitResult != SubmitResult.TimeOut)
                {
                    ++_idx;
                }
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            var res = HookerApi.Hook();
            if (!res)
            {
                MessageBox.Show("初始化失败");
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            _files = System.IO.Directory.GetFiles(@"E:\vehimg\2011\12\09\01\2");
        }

        private void button3_Click(object sender, EventArgs e)
        {
            HookerApi.SetFilePath(_files[_index]);
            _index++;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            webBrowser1.Navigate(LoginUrl);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            SetText("input", "name", "hphm", "川R12345");
            FireEvent("input", "name", "hphm", "onchange");
        }

        private void button5_Click(object sender, EventArgs e)
        {
            webBrowser1.Navigate(@"H:\EPolice.htm");
            // _browser.GoTo();
        }

        void FireEvent(string type, string attribute, string attName, string eventName)
        {
            var element = FindElement(type, attribute, attName);
            if (element != null)
            {
                element.InvokeMember(eventName);
            }
        }

        void SetText(string type, string attribute, string attName, string value)
        {
            var element = FindElement(type, attribute, attName);
            if (element != null)
            {
                element.SetAttribute("value", value);
                element.InvokeMember("onchange");
            }
        }

        string GetText(string type, string attribute, string attName)
        {
            var element = FindElement(type, attribute, attName);
            if (element != null)
            {
                return element.GetAttribute("value");
            }

            throw new Exception("element not found");
        }

        HtmlElement FindElement(string type, string attribute, string attName)
        {

            // Get a collection of all the tags with name "input";

            HtmlElementCollection tagsCollection = webBrowser1.Document.GetElementsByTagName(type);


            foreach (HtmlElement currentTag in tagsCollection)
            {

                // If the attribute of the current tag has the name attName

                if (currentTag.GetAttribute(attribute).Equals(attName))

                    // Then set its attribute "value".
                    return currentTag;

            }

            return null;
        }

        private void textBoxUrl_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return)
            {
                webBrowser1.Navigate(textBoxUrl.Text);
            }
        }

        void ClickButton(string attribute, string attName)
        {
            FireEvent("input", attribute, attName, "click");
        }


        private Record[] _records;

        private void button1_Click_1(object sender, EventArgs e)
        {
            var r = gridView1.GetRow(gridView1.FocusedRowHandle) as Record;
            if (r != null && webBrowser1.Document != null)
            {
                if (r.SubmitStatus == 1)
                {
                    MessageBox.Show("该条记录已经提交过了");
                    return;
                }
                FillForm(r, gridView1.GetFocusedDataSourceRowIndex());
            }

        }

        private void FillLprNumber(string lprNumber)
        {
            SetText("input", "name", "hphm", lprNumber);
        }

        //违法时间
        private void FillCaptureTime(DateTime time)
        {
            SetText("input", "name", "wfsj", time.ToString(AppConst.TimeFormatString));
        }

        //道路代码
        private void FillRoadNo(string no)
        {
            FireEvent("input", "name", "wfdd", "onfocus");
            SetText("input", "name", "wfdd", no);
        }

        //采集方式
        private void FillCjfs(string cjfs)
        {
            SetText("select", "name", "cjfs", cjfs);
        }

        //车辆类型
        private void FillCllx(string cllx)
        {
            SetText("select", "name", "hpzl", cllx);
        }

        //违法类型
        private void FillViolationCode(string code)
        {
            SetText("input", "name", "wfxw", code);
        }

        //填入图片, idx 从 0 开始
        private void FillImage(int idx, string path)
        {
            HookerApi.SetFilePath(path);
            ClickButton("name", "uploadfile" + (idx + 1).ToString(CultureInfo.InvariantCulture));
        }


        //提交当前表单
        private void SubmitForm()
        {
            ClickButton("name", "bc");
        }

        //必填项目:车型 车牌号码 违法代码 违法时间 道路代码 采集方式
        private SubmitResult FillForm(Record record, int rowIndex)
        {
            var result = SubmitResult.TimeOut;
            var msg = string.Empty;

            _readyToSubmit = false;

            webBrowser1.Navigate(SubmitUrl);
            var timerBegin = DateTime.Now;
            while (!_readyToSubmit)
            {
                if (DateTime.Now - timerBegin > TimeSpan.FromMinutes(1))
                {
                    msg = "等待载入提交页面超时";
                    result = SubmitResult.TimeOut;
                    goto Out;
                }
                Application.DoEvents();
            }

            var cllx = AppConst.FindPoliceCarCodeByProgramCode(record.CarType);
            FillCllx(cllx ?? string.Empty);
            FillLprNumber(record.LprNumber);
            var policeCode = AppConst.ConvertViolationCodeToPoliceCode(record.ViolationCode);
            FillViolationCode(policeCode);
            FillCaptureTime(record.CaptureTime);
            var roadCode = AppConst.FindRoadCodeByRoad(record.RoadNo);
            FillRoadNo(roadCode ?? String.Empty);
            FillLuKou(record.RoadNo);
            FillCjfs(record.CaptureMethod);
            FillImages(record);

            LogMessage("fill done, wait for car owner query result");

            var timerStart = DateTime.Now;

            while (true)
            {
                if ((DateTime.Now - timerStart) > TimeSpan.FromMinutes(1))
                {
                    msg = "等待车主查询结果超时";
                    result = SubmitResult.TimeOut;
                    goto Out;
                }

                if (!string.IsNullOrEmpty(GetText("input", "name", "jdcsyr")))
                {
                    break;
                }

                Application.DoEvents();

            }

            LogMessage("car owner got");

            if (!checkEditDonotSubmit.Checked)
            {
                HookerApi.ClearErrorMessage();
                LogMessage("submit form");
                SubmitForm();

                LogMessage("wait for submit result");
                timerStart = DateTime.Now;
                while (true)
                {
                    //LogMessage("before get error message");
                    var sb = new StringBuilder(1024);
                    HookerApi.GetErrorMessage(sb);
                    if (sb.Length != 0)
                    {
                        msg = sb.ToString();
                        break;
                    }
                    //LogMessage("after get error message");
                    if ((DateTime.Now - timerStart) > TimeSpan.FromMinutes(5))
                    {
                        msg = "等待提交结果超时";
                        LogMessage(msg);
                        result = SubmitResult.TimeOut;
                        goto Out;
                    }


                    Application.DoEvents();

                }

                LogMessage("submit form finished, result: " + msg);
                result = msg.Contains("成功") ? SubmitResult.Success : SubmitResult.Fail;
            }

        Out:

            record.SubmitStatus = result == SubmitResult.Success ? 1 : 2;
            record.SubmitResultInfo = msg;
            var h = gridView1.GetRowHandle(rowIndex);

            gridView1.RefreshRow(h);

            return result;
        }

        private void FillLuKou(string roadNo)
        {
            var lukou = AppConst.FindLukouByRoad(roadNo);
            SetText("input", "name", "lddm", lukou ?? "");
        }

        private void FillImages(Record record)
        {
            var imgParentDir = GetImageRootDirectory(record);
            var path1 = Path.Combine(imgParentDir, record.ImageRelativePath1);
            if (File.Exists(path1))
            {
                FillImage(0, path1);
            }

            var path2 = Path.Combine(imgParentDir, record.ImageRelativePath2);
            if (File.Exists(path2))
            {
                FillImage(1, path2);
            }
            else if (File.Exists(path1))
            {
                FillImage(1, path1);
            }

            var path3 = Path.Combine(imgParentDir, record.ImageRelativePath3);
            if (File.Exists(path3))
            {
                FillImage(2, path3);
            }
            else if (File.Exists(path1))
            {
                FillImage(2, path1);
            }
        }

        private string GetImageRootDirectory(Record record)
        {
            var imgRoot = textBoxFileName.Text.Replace(AppConst.FileExtension, "") + "_图片";
            var imgParentDir = Path.Combine(imgRoot, record.TxUrl);
            return imgParentDir;
        }


        private void button3_Click_1(object sender, EventArgs e)
        {
            FillLprNumber("川R12345");
        }

        private void button4_Click_1(object sender, EventArgs e)
        {
            FillCaptureTime(DateTime.Now.AddHours(-1));
        }

        private async void buttonBrowseForFile_Click(object sender, EventArgs e)
        {
            HookerApi.EnableHook(false);
            var dlg = new OpenFileDialog();
            dlg.Filter = AppConst.FilterExtension;
            var res = dlg.ShowDialog(this);
            HookerApi.EnableHook(true);
            if (res == DialogResult.OK)
            {
                buttonBrowseForFile.Enabled = false;
                Cursor.Current = Cursors.WaitCursor;
                textBoxFileName.Text = dlg.FileName;

                try
                {
                    _records = await DataExporter.Helper.ReadFileAsync(dlg.FileName);
                    gridControl1.DataSource = _records;
                    _fileDirectory = Path.GetDirectoryName(dlg.FileName);

                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, "读取文件发生错误\r\n\r\n" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    Cursor.Current = Cursors.Default;
                    buttonBrowseForFile.Enabled = true;
                }
            }
        }



        private void button5_Click_1(object sender, EventArgs e)
        {
            FillRoadNo("30503");
        }

        private void button7_Click(object sender, EventArgs e)
        {
            FillCjfs("4");
        }

        private void button8_Click(object sender, EventArgs e)
        {
            FillCllx("B21");
        }

        private int _idx = 0;
        private StreamWriter _writer;
        private bool _stopSubmit = false;

        private void buttonSubmitAll_Click(object sender, EventArgs e)
        {
            if (_records != null && webBrowser1.Document != null)
            {
                _stopSubmit = false;
                StartSubmit();
            }
        }

        private void StopSubmit()
        {
            _stopSubmit = true;
            _submitTimer.Stop();
            buttonBrowseForFile.Enabled = true;
            ShowSubmitButton(true);
        }

        private void StartSubmit()
        {
            progressBar1.EditValue = 0;
            progressBar1.Properties.Maximum = _records.Length;
            panelProgress.Visible = true;
            buttonBrowseForFile.Enabled = false;
            ShowSubmitButton(false);
            _idx = 0;
            _submitTimer.Start();

        }

        private void exportToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void buttonStopSubmit_Click(object sender, EventArgs e)
        {
            StopSubmit();
        }

        private void ShowSubmitButton(bool show)
        {
            buttonStopSubmit.Visible = !show;
            buttonSubmitAll.Visible = show;
        }



        private void button2_Click_1(object sender, EventArgs e)
        {
            var sb = new StringBuilder(1024);
            HookerApi.GetErrorMessage(sb);
            if (sb.Length == 0)
            {
                sb.Append("没有错误信息");
            }
            MessageBox.Show(sb.ToString());
        }

        private void LogMessage(string msg)
        {
            _writer.WriteLine(msg);
            _writer.Flush();
        }

        private void toolTipController1_GetActiveObjectInfo(object sender, DevExpress.Utils.ToolTipControllerGetActiveObjectInfoEventArgs e)
        {
            if (e.SelectedControl != gridControl1) return;

            ToolTipControlInfo info = null;
            //Get the view at the current mouse position 
            var view = gridControl1.GetViewAt(e.ControlMousePosition) as GridView;
            if (view == null) return;
            //Get the view's element information that resides at the current position 
            GridHitInfo hi = view.CalcHitInfo(e.ControlMousePosition);
            //Display a hint for row indicator cells 
            if (hi.HitTest == GridHitTest.RowCell && hi.Column.FieldName == "SubmitStatus")
            {

                //An object that uniquely identifies a row indicator cell 
                var r = view.GetRow(hi.RowHandle) as Record;
                info = new ToolTipControlInfo(r, r.SubmitResultInfo);
            }
            //Supply tooltip information if applicable, otherwise preserve default tooltip (if any) 
            if (info != null)
                e.Info = info;

        }

        private void checkEdit1_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void gridView1_RowClick(object sender, RowClickEventArgs e)
        {
            
        }

        private void ShowImages(Record row)
        {
            if (row != null)
            {
                ClearGallery();
                var imageRoot = GetImageRootDirectory(row);
                ShowImage(imageRoot, row.FImageRelativePath1);
                ShowImage(imageRoot, row.FImageRelativePath2);
                ShowImage(imageRoot, row.FImageRelativePath3);
            }
        }

        private void ClearGallery()
        {
            galleryControl1.Gallery.Groups[0].Items.Clear();
        }

        private void ShowImage(string baseDir, string relativePath)
        {
            if (relativePath != null)
            {

                var path = Path.Combine(baseDir, relativePath);
                if (File.Exists(path))
                {
                    var bytes = File.ReadAllBytes(path);
                    var img = Image.FromStream(new MemoryStream(bytes));
                    var galleryItem = new GalleryItem(img, null, null);
                    galleryItem.HoverImage = img;
                    this.galleryControl1.Gallery.Groups[0].Items.Add(galleryItem);
                }
            }
        }

        private void gridView1_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            var row = gridView1.GetRow(e.FocusedRowHandle) as Record;
            ShowImages(row);

        }
    }

    internal enum SubmitResult
    {
        TimeOut,
        Success,
        Fail
    }
}
